#pragma once
#include <cstring>
#include <iostream>
#include <string>
#include <memory>
#include "Socket.hpp"
#include <sstream>
#include <jsoncpp/json/json.h>
#include "Log.hpp"
#include<functional>
using namespace LogMoudle;
using namespace SocketMoudle;
// 自定义网络版本的计算器
// 约定好字段的含义
class Request
{
private:
    int _x;
    int _y;
    char _oper;

public:
    Request() {}
    ~Request() {}
    Request(int x,int y,char oper):_x(x),_y(y),_oper(oper){}
    std::string serialize()
    {
        // 序列化为字符串
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;
        Json::FastWriter writer;
        std::string json_str = writer.write(root);
        return json_str;
    }
    bool deserialize(std::string &in)
    {
        // 反序列化为Request对象
        Json::Value root;
        Json::Reader reader;
        if (reader.parse(in, root))
        {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
            return true;
        }
        return false;
    }
    int getX() const{ return this->_x; }
    int getY() const{ return this->_y; }
    char getOper() const{ return this->_oper; }
};
class Response
{
private:
    int _result; // 运算结果，无法区分是计算结果还是异常值
    int _code;   // 状态码
public:
    Response(int result, int code) : _result(result), _code(code) {}
    Response() {}
    ~Response() {}
    std::string serialize()
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        Json::FastWriter writer;
        return writer.write(root);
    }
    bool deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        if (reader.parse(in, root))
        {
            _result = root["result"].asInt();
            _code = root["code"].asInt();
            return true;
        }
        return false;
    }
    void setResult(int result) { this->_result = result; }
    void setCode(int code) { this->_code = code; }
    int getResult() const { return this->_result; }
    int getCode() const { return this->_code; }
};
// 协议必须解决两个问题：
// request,response的序列化和反序列化
// 读到完整的请求（Tcp需要考虑，Udp不需要考虑）
// 规定我们在发送时前面先要发送这个请求的长度
// num\r\n{json字符串}
const std::string kHeader = "\r\n";
using func_t =std::function<Response(const Request&req)>;
class Protocol
{
private:
    // Request _request;
    // Response _response;
    func_t _func;
public:
    template<typename func>
    Protocol(func task):_func(task){}
    Protocol(){}
    ~Protocol() {}
    std::string Encode(const std::string &request)
    {
        int len = request.size();
        std::string header = std::to_string(len) + kHeader;
        return header + request + kHeader;
    }
    bool Decode(std::string &buffer, std::string *packge)
    {
        // 解析包头
        // 判断报文完整性
        // 提取完整报文
        ssize_t pos = buffer.find(kHeader);
        if (pos == std::string::npos)
        {
            return false;
        }
        // 一定有长度
        std::string lenstr = buffer.substr(0, pos);
        int len = std::stoi(lenstr);
        if (len <= 0)
            LOG(LogLevel::ERROR) << "报文长度不合法";
        int target_len = lenstr.size() + 2 * kHeader.size() + len; // 正常大小
        if ((int)buffer.size() < target_len)
        {
            // 报文不完整
            return false;
        }
        // 一定有一个完整的报文
        *packge = buffer.substr(pos + kHeader.size(), len);
        buffer.erase(0, pos + kHeader.size() + len + kHeader.size());
        return true;
    }
    std::string Execute(std::string &package)
    {
               //完整报文
               //反序列化解析
               Request req;
               bool ok=req.deserialize(package);
               if(!ok)return "";
               //完成业务
               Response resp=_func(req);
               //序列化
               std::string json_str=resp.serialize();
              //加上报头
              std::string send_str=Encode(json_str);
              return send_str;
    }
    bool GetResponse(std::shared_ptr<Socket>&client,std::string&response,Response&resp){
        //面向字节流，不能保证是一个完整的报文
        while(true){
        int n=client->Recv(&response);
        if(n>0){
            //成功
            std::string package;
            int ret=Decode(response, &package);
            if(!ret)return false;
            //完全报文
            //反序列化
            bool ok=resp.deserialize(package);
            if(!ok)return false;
            return true;
        }else if(n==0){
           LOG(LogLevel::INFO)<<"服务器断开连接";
           return false;
           break;
        }
        else{
            LOG(LogLevel::INFO)<<"服务器异常断开连接";
            return false;
            break;
        }
        return false;
        }
    }
    std::string BuildRequeststring(int x,int y,char oper){
        //1.构建请求
        Request req(x,y,oper);
        //2.序列化
        std::string json_string=req.serialize();
        //3.加报头
        return Encode(json_string);
    }
};